#pragma once

#include "Unit.h"

class CreatureLooterMgr;

class Creature : public Unit
{
public:
	Creature(OBJECT_TYPE objType);
	virtual ~Creature();

	bool InitCreature(const CreatureSpawn* pSpawn);

	virtual bool SubInit();
	virtual void SubUpdate(uint64 diffTime);

	virtual void OnPushToWorld();
	virtual void OnPreLeaveWorld();
	virtual void OnDelete();

	virtual void BuildCreatePacketForPlayer(INetPacket& pck, Player* pPlayer);

	void SetSpawnPrivate(const std::shared_ptr<CreatureSpawn>& pSpawn);
	const std::shared_ptr<CreatureSpawn>& GetSpawnPrivate() const;

	uint32 GetSpawnId() const { return m_pSpawn->spawnId; }
	const CreatureSpawn* GetSpawn() const { return m_pSpawn; }
	const vector3f& GetSpawnPos() const { return m_spawnPos; }

private:
	const CreatureSpawn* m_pSpawn;
	std::shared_ptr<CreatureSpawn> m_pSpawnPrivate;
	vector3f m_spawnPos;

protected:
	void SubInitLuaEnv();
private:
	bool m_isBehaviorTree;

public:
	u8 GetElite() const { return m_pProto->charElite; }

public:
	virtual void LoadBase(double attrs[]);
	virtual void LoadBody(AttrPartProxy& proxy);
	virtual void LoadEquip(AttrPartProxy& proxy);
	virtual void LoadExtraAttrs();

public:
	virtual bool TestInteresting(AoiActor *actor) const;
	virtual void OnAddMarker(AoiActor *actor);
	virtual void OnRemoveMarker(AoiActor *actor);

public:
	virtual void SetTarget(Unit* pTarget);
	Unit* SelectMaxHatredEnemy();
private:
	void UpdateTarget();
	void CleanEnemyList();
	bool IsEnemyAvail(Unit* pEnemy, bool isCheckAttack);

public:
	virtual bool IsHostile(const Unit* pTarget) const;
private:
	virtual void OnLoseHP(Unit* pHurter, uint64 hurtValue);
	virtual void OnDead(Unit* pKiller);
	virtual void OnResetToIdle();
	void RecoveryHPMPValue4ResetToIdle();
	void AddToLooterList(Player* pPlayer, uint64 damage);
	void ClearLooterList();
	void Loot();
	CreatureLooterMgr* m_pLooterMgr;

public:
	bool CanIdlePatrol() const;
	void UpdateIdlePatrol();
private:
	void UpdateRandomPoint();
	void UpdateWayPoint();
	void ResetIdlePatrol();
	const WayPoint* m_pNextWP;
	uint64 m_iPatrolMoveCD;

public:
	bool IsVisibleByPlayer(const Player* pPlayer);

public:
	virtual void OnChangePosition();

public:
	class EtherealObject;
	EtherealObject* AttachEtherealObject(float radius, int flags);
	void DetachEtherealObject(EtherealObject* pEObj);
	void RemoveAllEtherealObjects();
private:
	void MoveEtherealObjects();
	std::vector<EtherealObject*> m_etherealObjects;

public:
	void ObjectHookEvent_OnEObjUnitEnter(EtherealObject* pEObj, Unit* pUnit);
	void ObjectHookEvent_OnEObjUnitLeave(EtherealObject* pEObj, Unit* pUnit);
};
